package com.zhentao.service.impl;

import com.zhentao.service.UserService;
import com.zhentao.util.Result;
import com.zhentao.util.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

import static com.zhentao.util.RedisConstants.USER_SIGN_KEY;
import com.zhentao.pojo.TbSign;
import com.zhentao.service.TbSignService;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private TbSignService tbSignService;


    @Override
    public Result sign() {
        // 1.获取当前登录用户
        Long userId = Long.valueOf(UserHolder.getUser().getId());
        // 2.获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3.拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;
        // 4.获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5.写入Redis SETBIT key offset 1
        stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
        return Result.OK();
    }

    @Override
    public Result signCount() {
        // 1.获取当前登录用户
        Long userId = Long.valueOf(UserHolder.getUser().getId());
        // 2.获取日期
        LocalDateTime now = LocalDateTime.now();
        // 3.拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = USER_SIGN_KEY + userId + keySuffix;
        // 4.获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        // 5.获取本月截止今天为止的所有的签到记录，返回的是一个十进制的数字 BITFIELD sign:5:202203 GET u14 0
        List<Long> result = stringRedisTemplate.opsForValue().bitField(
                key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
        );
        if (result == null || result.isEmpty()) {
            // 没有任何签到结果
            return Result.OK(0);
        }
        Long num = result.get(0);
        if (num == null || num == 0) {
            return Result.OK(0);
        }
        // 6.循环遍历
        int count = 0;
        while (true) {
            // 6.1.让这个数字与1做与运算，得到数字的最后一个bit位  // 判断这个bit位是否为0
            if ((num & 1) == 0) {
                // 如果为0，说明未签到，结束
                break;
            }else {
                // 如果不为0，说明已签到，计数器+1
                count++;
            }
            // 把数字右移一位，抛弃最后一个bit位，继续下一个bit位
            num >>>= 1;
        }
        return Result.OK(count);
    }

    @Override
    public Result sign(String userId) {
        if (userId == null || userId.isEmpty()) {
            System.out.println("签到失败：用户ID为空");
            return Result.ERROR("用户ID不能为空");
        }

        try {
            System.out.println("处理签到请求，用户ID: " + userId);
            // 获取日期
            LocalDateTime now = LocalDateTime.now();
            // 拼接key
            String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
            String key = USER_SIGN_KEY + userId + keySuffix;
            // 获取今天是本月的第几天
            int dayOfMonth = now.getDayOfMonth();

            // 检查今天是否已经签到
            Boolean isSigned = stringRedisTemplate.opsForValue().getBit(key, dayOfMonth - 1);
            if (Boolean.TRUE.equals(isSigned)) {
                System.out.println("用户 " + userId + " 今天已经签到过了");
                return Result.OK("今日已签到");
            }

            // 写入Redis SETBIT key offset 1
            stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);

            // 将签到数据存入数据库
            TbSign sign = new TbSign();
            sign.setUserId(Long.valueOf(userId));
            sign.setYear(now.getYear());
            sign.setMonth(now.getMonthValue());
            sign.setDate(java.sql.Date.valueOf(now.toLocalDate()));
            sign.setIsBackup(0); // 默认非备份

            // 保存到数据库
            boolean saved = tbSignService.save(sign);
            if (!saved) {
                System.out.println("用户 " + userId + " 签到数据保存到数据库失败");
                // 注意：即使数据库保存失败，Redis中的签到记录已经成功，所以仍然返回成功
            } else {
                System.out.println("用户 " + userId + " 签到数据成功保存到数据库");
            }

            System.out.println("用户 " + userId + " 签到成功，日期: " + now);
            return Result.OK();
        } catch (Exception e) {
            System.out.println("签到异常: " + e.getMessage());
            e.printStackTrace();
            return Result.ERROR("签到失败: " + e.getMessage());
        }
    }

    @Override
    public Result signCount(String userId) {
        if (userId == null || userId.isEmpty()) {
            System.out.println("获取签到统计失败：用户ID为空");
            return Result.ERROR("用户ID不能为空");
        }

        try {
            System.out.println("处理获取签到统计请求，用户ID: " + userId);
            // 获取日期
            LocalDateTime now = LocalDateTime.now();
            // 拼接key
            String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
            String key = USER_SIGN_KEY + userId + keySuffix;
            // 获取今天是本月的第几天
            int dayOfMonth = now.getDayOfMonth();
            // 获取本月截止今天为止的所有的签到记录，返回的是一个十进制的数字 BITFIELD sign:5:202203 GET u14 0
            List<Long> result = stringRedisTemplate.opsForValue().bitField(
                    key,
                    BitFieldSubCommands.create()
                            .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0)
            );
            if (result == null || result.isEmpty()) {
                // 没有任何签到结果
                System.out.println("用户 " + userId + " 没有签到记录");
                return Result.OK(0);
            }
            Long num = result.get(0);
            if (num == null || num == 0) {
                System.out.println("用户 " + userId + " 签到记录为0");
                return Result.OK(0);
            }
            // 循环遍历
            int count = 0;
            while (true) {
                // 让这个数字与1做与运算，得到数字的最后一个bit位  // 判断这个bit位是否为0
                if ((num & 1) == 0) {
                    // 如果为0，说明未签到，结束
                    break;
                } else {
                    // 如果不为0，说明已签到，计数器+1
                    count++;
                }
                // 把数字右移一位，抛弃最后一个bit位，继续下一个bit位
                num >>>= 1;
            }
            System.out.println("用户 " + userId + " 连续签到天数: " + count);
            return Result.OK(count);
        } catch (Exception e) {
            System.out.println("获取签到统计异常: " + e.getMessage());
            e.printStackTrace();
            return Result.ERROR("获取签到次数失败: " + e.getMessage());
        }
    }
}
